/***************************************************************************
 *                                                                         *
 * Copyright (c) 2007 - 2009 Nuvoton Technology Corp. All rights reserved.*
 *                                                                         *
 ***************************************************************************/
 

#ifdef ECOS
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "drv_api.h"
#include "diag.h"
#include "wbio.h"
#include "NUC900_GE.h"
#include "NUC900_reg.h"
#else
#include <stdio.h>
#include "NUC900_GE.h"
#include "wbio.h"
#ifdef _NUC900_
#include "NUC900_reg.h"
#else
#include "reg702.h"
#endif
#endif

#define ABS(x)		(((x)>0)?(x):-(x))
#define MAX(a,b)	(((a)>(b))?(a):(b))

/* octant code of line drawing */

#define	XpYpXl		(0<<1)   // XY octant position is 1~3 in Control register
#define	XpYpYl		(1<<1)
#define XpYmXl  	(2<<1)
#define XpYmYl  	(3<<1)
#define XmYpXl  	(4<<1)
#define XmYpYl  	(5<<1)
#define XmYmXl  	(6<<1)
#define XmYmYl  	(7<<1)
/*
static UINT16 LinePatternData[6] =
{ 
  0xffff, // SOLID
  0xcccc, // DASH
  0xaaaa, // DOT
  0xe4e4, // DASHDOT
  0xeaea, // DASHDOTDOT
  0x0000  // NULL
};
*/

///////////////////////////////////////////////////////////////////////////////
//
// Function: draw_solid_line()
//
// Description:
//   Draw a solid line. 
//
///////////////////////////////////////////////////////////////////////////////
void draw_solid_line(int x1, int y1, int x2, int y2, int color)
{
  int abs_X, abs_Y, min, max;
  UINT32 step_constant, initial_error, direction_code;
  UINT32 cmd32, dest_pitch, dest_start;
 
#ifdef DEBUG 
  printf("draw_solid_line():\n");
  printf("(%d,%d)-(%d,%d)\n", x1, y1, x2, y2);
  printf("color=0x%x\n", color);
#endif 

  abs_X = ABS(x2-x1);  //absolute value
  abs_Y = ABS(y2-y1);  //absolute value
  if (abs_X > abs_Y) // X major
  {	
    //printf("X major\n");
    max = abs_X;
    min = abs_Y;
    
    step_constant = (((UINT32)(2*(min-max))) << 16) | (UINT32)(2*min);
    initial_error = (((UINT32)(2*(min)-max)) << 16) | (UINT32)(max);
        
    if (x2 > x1) // +X direction
    {
      if (y2 > y1) // +Y direction
         direction_code = XpYpXl;
      else // -Y direction   	
         direction_code = XpYmXl;
    }
    else // -X direction
    {
      if (y2 > y1) // +Y direction
         direction_code = XmYpXl;
      else // -Y direction   	
         direction_code = XmYmXl;
    }
  }		
  else // Y major
  {
    //printf("Y major\n");
    max = abs_Y;
    min = abs_X;
    
    step_constant = (((UINT32)(2*(min-max))) << 16) | (UINT32)(2*min);
    initial_error = (((UINT32)(2*(min)-max)) << 16) | (UINT32)(max);
  
    if (x2 > x1) // +X direction
    {
      if (y2 > y1) // +Y direction
         direction_code = XpYpYl;
      else // -Y direction   	
         direction_code = XpYmYl;
    }
    else // -X direction
    {
      if (y2 > y1) // +Y direction
         direction_code = XmYpYl;
      else // -Y direction   	
         direction_code = XmYmYl;    	
    }
  }
  
  outpw(REG_2D_GEBER, step_constant);
  outpw(REG_2D_GEBIR, initial_error);
  
  cmd32 = 0x008b0000 | direction_code;
  
  outpw(REG_2D_GEC, cmd32);

  outpw(REG_2D_GEBC, make_color(color)); 
  outpw(REG_2D_GEFC, make_color(color)); 
  
  dest_pitch = GFX_WIDTH << 16; // pitch in pixel
  outpw(REG_2D_GESDP, dest_pitch);

  outpw(REG_2D_GEXYDORG, (int)GFX_START_ADDR);

  dest_start = y1 << 16 | x1;
  outpw(REG_2D_GEDSXYL, dest_start);

  if (_ClipEnable)
  {
    cmd32 |= 0x00000200;
    if (_OutsideClip)
    {
      cmd32 |= 0x00000100;
    }
    outpw(REG_2D_GEC, cmd32);
    outpw(REG_2D_GECBTL, _ClipTL);
    outpw(REG_2D_GECBBR, _ClipBR);
  }  
  
  //outpw(REG_2D_GEMC, inpw(REG_2D_GEMC)); // address caculation, no nothing

  outpw(REG_2D_GETG, 1); 
  
  while ((inpw(REG_2D_GEINTS)&0x01)==0); // wait for command complete  
  
  outpw(REG_2D_GEINTS, 1); // clear interrupt status
}


///////////////////////////////////////////////////////////////////////////////
//
// Function: draw_styled_line()
//
// Description:
//   Draw a styled line. 
//
///////////////////////////////////////////////////////////////////////////////
void draw_styled_line(int x1, int y1, int x2, int y2, int style, int fgcolor, int bkcolor, int draw_mode)
{
  int abs_X, abs_Y, min, max;
  UINT32 step_constant, initial_error, direction_code;
  UINT32 cmd32, dest_pitch, dest_start;
  UINT32 temp32, line_control_code;
  
  abs_X = ABS(x2-x1);
  abs_Y = ABS(y2-y1);
  if (abs_X > abs_Y) // X major
  {	
    //printf("X major\n");
    max = abs_X;
    min = abs_Y;
    
    step_constant = (((UINT32)(2*(min-max))) << 16) | (UINT32)(2*min);
    initial_error = (((UINT32)(2*min-max)) << 16) | (UINT32)(max);
        
    if (x2 > x1) // +X direction
    {
      if (y2 > y1) // +Y direction
         direction_code = XpYpXl;
      else // -Y direction   	
         direction_code = XpYmXl;
    }
    else // -X direction
    {
      if (y2 > y1) // +Y direction
         direction_code = XmYpXl;
      else // -Y direction   	
         direction_code = XmYmXl;    	
    }
  }		
  else // Y major
  {
    //printf("Y major\n");
    max = abs_Y;
    min = abs_X;
    
    step_constant = (((UINT32)(2*(min-max))) << 16) | (UINT32)(2*min);
    initial_error = (((UINT32)(2*min-max)) << 16) | (UINT32)(max);
  
    if (x2 > x1) // +X direction
    {
      if (y2 > y1) // +Y direction
         direction_code = XpYpYl;
      else // -Y direction   	
         direction_code = XpYmYl;
    }
    else // -X direction
    {
      if (y2 > y1) // +Y direction
         direction_code = XmYpYl;
      else // -Y direction   	
         direction_code = XmYmYl;    	
    }
  }
  
  outpw(REG_2D_GEBER, step_constant);
  outpw(REG_2D_GEBIR, initial_error);
  
  cmd32 = 0x009b0000 | direction_code; // styled line
  if (draw_mode==MODE_TRANSPARENT)
  {
    //cmd32 |= 0x00004000; // default is MODE_OPAQUE
    cmd32 |= 0x00008000; // default is MODE_OPAQUE, //smf
  }
  outpw(REG_2D_GEC, cmd32);

  outpw(REG_2D_GEBC, make_color(bkcolor)); 
  outpw(REG_2D_GEFC, make_color(fgcolor)); 
  
  dest_pitch = GFX_WIDTH << 16; // pitch in pixel
  outpw(REG_2D_GESDP, dest_pitch);
  
  /******************/
  outpw(REG_2D_GEXYDORG, (int)GFX_START_ADDR);   // smf
  /******************/
  
  dest_start = y1 << 16 | x1;
  outpw(REG_2D_GEDSXYL, dest_start);
    
  if (_ClipEnable)
  {
    cmd32 |= 0x00000200;
    if (_OutsideClip)
    {
      cmd32 |= 0x00000100;
    }
    outpw(REG_2D_GEC, cmd32);
    outpw(REG_2D_GECBTL, _ClipTL);
    outpw(REG_2D_GECBBR, _ClipBR);
  }  
  
  //line_control_code = (UINT32)LinePatternData[style];  // smf
  line_control_code = style;
  temp32 = inpw(REG_2D_GEMC) & 0x0000ffff;
  temp32 = (line_control_code << 16) | temp32;
  
  outpw(REG_2D_GEMC, temp32); // address caculation
    
  outpw(REG_2D_GETG, 1); 
  
  while ((inpw(REG_2D_GEINTS)&0x01)==0); // wait for command complete  
  
  outpw(REG_2D_GEINTS, 1); // clear interrupt status
}
 
 